/*
---- MAIN THREAD
*/
var
  TestCarGen: CarGenerator
  TestPickup: Pickup
end
thread MAIN
  name "MAIN"

  // Init gameworld
  add_hospital_restart(-449.7836, -341.3995, 33.5024, 83.1352)
  add_hospital_restart(341.4144, -1396.291, 31.5098, 47.53)
  add_hospital_restart(360.7675, -583.4315, 27.8269, 276.9074)
  add_hospital_restart(1838.495, 3672.222, 33.2783, 206.5448)
  add_hospital_restart(-242.2981, 6325.233, 31.4271, 335.2387)
  add_police_restart(-1093.89, -807.0834, 18.2612, 42.24)
  add_police_restart(360.8818, -1581.608, 28.2931, 23.6148)
  add_police_restart(-560.5718, -132.7783, 37.0586, 210.6082)
  add_police_restart(1856.352, 3682.061, 33.2672, 210.2006)
  add_police_restart(-440.7429, 6019.889, 30.4903, 314.9315)
  add_police_restart(639.1819, 1.765, 81.7865, 238.0365)
  add_police_restart(479.6391, -976.6794, 26.9839, 331.7253)

  // Starting as Trevor! Setting up stuff!
  var
    playerHash: GTA.Hash
    carHash: GTA.Hash
    hasModelLoaded: bool
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerCar: GTA.Vehicle
  end

  @playerHash = MISC.GET_HASH_KEY("player_two")
  STREAMING.REQUEST_MODEL(@playerHash)

  :CheckPlayerModelLoaded
  wait locked
  @hasModelLoaded = STREAMING.HAS_MODEL_LOADED(@playerHash)
  if
    @hasModelLoaded != false
  jump_if_false #CheckPlayerModelLoaded
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  PLAYER.SET_PLAYER_MODEL(@playerHandle, @playerHash)
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  PED.SET_PED_COMPONENT_VARIATION(@playerPed, 3, 5, 0, 0)
  PED.SET_PED_COMPONENT_VARIATION(@playerPed, 4, 5, 0, 0)
  PED.SET_PED_COMPONENT_VARIATION(@playerPed, 5, 2, 0, 0)
  PED.SET_PED_COMPONENT_VARIATION(@playerPed, 6, 5, 0, 0)
  PED.SET_PED_COMPONENT_VARIATION(@playerPed, 8, 4, 0, 0)
  PED.SET_PED_PROP_INDEX(@playerPed, 0, 7, 0, true, 0)
  STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(@playerHash)

  @carHash = MISC.GET_HASH_KEY("emperor2")
  STREAMING.REQUEST_MODEL(@carHash)

  :CheckCarModelLoaded
  wait locked
  @hasModelLoaded = STREAMING.HAS_MODEL_LOADED(@carHash)
  if
    @hasModelLoaded != false
  jump_if_false #CheckCarModelLoaded
  @playerCar = VEHICLE.CREATE_VEHICLE(@carHash, -483.291, -308.783, 35.385, 204.092, false, false, false)
  VEHICLE.SET_VEHICLE_COLOURS(@playerCar, 143, 35)
  PED.SET_PED_INTO_VEHICLE(@playerPed, @playerCar, -1)
  ENTITY.SET_VEHICLE_AS_NO_LONGER_NEEDED(@playerCar)
  STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(@carHash)

  var
    modelHash: GTA.Hash
  end

  // Parked car generator in front of the Observatory - Go Go Space Monkey Blista
  @modelHash = MISC.GET_HASH_KEY("blista3")
  $TestCarGen = create_car_generator(-414.259, 1164.613, 326.099, 163.468, @modelHash)
  $TestCarGen.Active = true

  // Weapon pickup under a tree at the Epsilon Program HQ - Heavy Pistol with 500 bullets
  @modelHash = MISC.GET_HASH_KEY("PICKUP_WEAPON_HEAVYPISTOL")
  $TestPickup = create_pickup(-684.452, 32.96, 41.115, @modelHash, 0, 500, 275000)

  // Create threads
  create_thread &MichaelSave
  create_thread &MichaelGarage
  create_thread &MichaelHangar
  create_thread &FranklinSave
  create_thread &FranklinGarage
  create_thread &FranklinHangar
  create_thread &TrevorSave
  create_thread &TrevorGarage
  create_thread &TrevorHangar
  create_thread &CarSpray1
  create_thread &CarSpray2
  create_thread &WastedBusted
  // create_thread &DressUp
  create_thread &PlayerSwitch
end

/*
---- Save Game for Michael
*/
thread MichaelSave
  name "MichaelSave"
  var
    saveBlip: Blip
  end
  @saveBlip = add_blip_with_icon(-822.529, -1223.196, 7.365, 40, 38)
  @saveBlip.Selectable = true
  @saveBlip.LongRange = true

  // Player distance check
  var
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end

  :CheckSaveGame
  @intplayer = get_internal_player_index()
  wait 0
  if and
    not is_on_mission()
    $is_player_wasted == false
    $is_player_busted == false
    @intplayer == 0
  jump_if_false #CheckSaveGame

  // Query player's disatance to the save spot...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -822.529, -1223.196, 7.365, true)

  // Draws a visible marker
  if
    @dist <= 50
  jump_if_false #CheckSaveGame
  GRAPHICS.DRAW_MARKER(1, -822.529, -1223.196, 6.365, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 255, 192, false, false, 2, true, null_str, null_str, false)

  // Player can now save the game via the menu
  if
    @dist <= 1
  jump_if_false #CheckSaveGame
  gosub &SaveGameFunc

  // NOTE: player handle may not be valid, if a savegame is loaded, so we need to query player handle again...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  ENTITY.SET_ENTITY_COORDS(@playerPed, -825.673, -1220.661, 6.966, false, false, false, true)
  ENTITY.SET_ENTITY_HEADING(@playerPed, 43.465)

  jump #CheckSaveGame
end

/*
---- Garage for Michael
*/
thread MichaelGarage
  name "MichaelGarage"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(-817.074, -1201.257, 6.435, 357, 38)
  @hangarMarker.Selectable = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 0
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -817.074, -1201.257, 6.435, false)
  @intplayer = get_internal_player_index()
  if or
    @dist > 15
    @z > 15
    @z < 4
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 0 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if and
    @dist < 50
    @intplayer == 0
  jump_if_false #StoreCars
  GRAPHICS.DRAW_MARKER(39, -817.074, -1201.257, 5.935, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 255, 192, false, false, 2, true, null_str, null_str, false)

  :StoreCars
  if
    @stored == false
  jump_if_false #MainCheck
  store_cars_from_angled_cube(-818.8398, -1195.692, 4.630597, -814.4955, -1207.762, 11.08519, 320.244, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(-818.8398, -1195.692, 4.630597, -814.4955, -1207.762, 11.08519, 320.244)
  forget_stored_cars_in_angled_cube(-818.8398, -1195.692, 4.630597, -814.4955, -1207.762, 11.08519, 320.244)
  @stored = false
  jump #MainCheck
end

/*
---- Airport Hangar for Michael
*/
thread MichaelHangar
  name "MichaelHangar"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(-1656.067, -3147.411, 12.73782, 359, 38)
  @hangarMarker.Selectable = true
  @hangarMarker.LongRange = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 250
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -1656.067, -3147.411, 12.73782, false)
  @intplayer = get_internal_player_index()
  if or
    @dist > 50
    @z > 30
    @z < 5
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 0 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if
    @stored == false
  jump_if_false #MainCheck
  store_cars_from_angled_cube(-1647.564, -3193.309, 8.30761, -1673.114, -3101.537, 29.47725, -28.6478955, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(-1647.564, -3193.309, 8.30761, -1673.114, -3101.537, 29.47725, -28.6478955)
  forget_stored_cars_in_angled_cube(-1647.564, -3193.309, 8.30761, -1673.114, -3101.537, 29.47725, -28.6478955)
  @stored = false
  jump #MainCheck
end

/*
---- Save Game for Franklin
*/
thread FranklinSave
  name "FranklinSave"
  var
    saveBlip: Blip
  end
  @saveBlip = add_blip_with_icon(-3024.2, 80.635, 11.608, 40, 2)
  @saveBlip.Selectable = true
  @saveBlip.LongRange = true

  // Player distance check
  var
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end

  :CheckSaveGame
  @intplayer = get_internal_player_index()
  wait 0
  if and
    not is_on_mission()
    $is_player_wasted == false
    $is_player_busted == false
    @intplayer == 1
  jump_if_false #CheckSaveGame

  // Query player's disatance to the save spot...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -3024.2, 80.635, 11.608, true)

  // Draws a visible marker
  if
    @dist <= 50
  jump_if_false #CheckSaveGame
  GRAPHICS.DRAW_MARKER(1, -3024.2, 80.635, 10.608, 0, 0, 0, 0, 0, 0, 1, 1, 1, 50, 168, 82, 192, false, false, 2, true, null_str, null_str, false)

  // Player can now save the game via the menu
  if
    @dist <= 1
  jump_if_false #CheckSaveGame
  gosub &SaveGameFunc

  // NOTE: player handle may not be valid, if a savegame is loaded, so we need to query player handle again...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  ENTITY.SET_ENTITY_COORDS(@playerPed, -3022.584, 82.215, 11.608, false, false, false, true)
  ENTITY.SET_ENTITY_HEADING(@playerPed, 320.056)

  jump #CheckSaveGame
end

/*
---- Garage for Franklin
*/
thread FranklinGarage
  name "FranklinGarage"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(-3052.909, 139.761, 11.065, 357, 2)
  @hangarMarker.Selectable = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 0
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -3052.909, 139.761, 11.065, false)
  @intplayer = get_internal_player_index()
  if or
    @dist > 15
    @z > 20
    @z < 5
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 1 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if and
    @dist < 50
    @intplayer == 1
  jump_if_false #StoreCars
  GRAPHICS.DRAW_MARKER(39, -3052.909, 139.761, 10.565, 0, 0, 0, 0, 0, 0, 1, 1, 1, 50, 168, 82, 192, false, false, 2, true, null_str, null_str, false)

  :StoreCars
  if
    @stored == false
  jump_if_false #MainCheck
  store_cars_from_angled_cube(-3055.385, 145.1221, 9.496418, -3051.141, 134.3363, 15.92931, 87.088, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(-3055.385, 145.1221, 9.496418, -3051.141, 134.3363, 15.92931, 87.088)
  forget_stored_cars_in_angled_cube(-3055.385, 145.1221, 9.496418, -3051.141, 134.3363, 15.92931, 87.088)
  @stored = false
  jump #MainCheck
end

/*
---- Airport Hangar for Franklin
*/
thread FranklinHangar
  name "FranklinHangar"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(-1276.007, -3388.756, 12.73782, 359, 2)
  @hangarMarker.Selectable = true
  @hangarMarker.LongRange = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 250
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -1276.007, -3388.756, 12.73782, false)
  @intplayer = get_internal_player_index()
  if or
    @dist > 50
    @z > 35
    @z < 5
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 1 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if
    @stored == false
  jump_if_false #MainCheck
  store_cars_from_angled_cube(-1268.428, -3433.557, 34.43299, -1292.99, -3342.538, 8.30761, -28.6478955, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(-1268.428, -3433.557, 34.43299, -1292.99, -3342.538, 8.30761, -28.6478955)
  forget_stored_cars_in_angled_cube(-1268.428, -3433.557, 34.43299, -1292.99, -3342.538, 8.30761, -28.6478955)
  @stored = false
  jump #MainCheck
end

/*
---- Save Game for Trevor
*/
thread TrevorSave
  name "TrevorSave"
  var
    saveBlip: Blip
  end
  @saveBlip = add_blip_with_icon(-1149.755, -1522.102, 10.628, 40, 17)
  @saveBlip.Selectable = true
  @saveBlip.LongRange = true

  // Player distance check
  var
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end

  :CheckSaveGame
  @intplayer = get_internal_player_index()
  wait 0
  if and
    not is_on_mission()
    $is_player_wasted == false
    $is_player_busted == false
    @intplayer == 2
  jump_if_false #CheckSaveGame

  // Query player's disatance to the save spot...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -1149.755, -1522.102, 10.628, true)

  // Draws a visible marker
  if
    @dist <= 50
  jump_if_false #CheckSaveGame
  GRAPHICS.DRAW_MARKER(1, -1149.755, -1522.102, 9.628, 0, 0, 0, 0, 0, 0, 1, 1, 1, 230, 104, 14, 192, false, false, 2, true, null_str, null_str, false)

  // Player can now save the game via the menu
  if
    @dist <= 1
  jump_if_false #CheckSaveGame
  gosub &SaveGameFunc

  // NOTE: player handle may not be valid, if a savegame is loaded, so we need to query player handle again...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  ENTITY.SET_ENTITY_COORDS(@playerPed, -1147.557, -1522.852, 10.638, false, false, false, true)
  ENTITY.SET_ENTITY_HEADING(@playerPed, 312.343)

  jump #CheckSaveGame
end

/*
---- Garage for Trevor
*/
thread TrevorGarage
  name "TrevorGarage"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(-1152.812, -1525.28, 4.259, 357, 17)
  @hangarMarker.Selectable = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 0
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -1152.812, -1525.28, 4.259, false)
  @intplayer = get_internal_player_index()
  if or
    @z > 7.5
    @z < 0
    @dist > 20
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 2 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if and
    @dist < 50
    @intplayer == 2
  jump_if_false #StoreCars
  GRAPHICS.DRAW_MARKER(39, -1152.812, -1525.28, 4.259, 0, 0, 0, 0, 0, 0, 1, 1, 1, 230, 104, 14, 192, false, false, 2, true, null_str, null_str, false)

  :StoreCars
  if
    @stored == false
  jump_if_false #MainCheck
  store_cars_from_angled_cube(-1161.654, -1519.679, 2.121554, -1143.231, -1530.795, 6.398511, 213.778, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(-1161.654, -1519.679, 2.121554, -1143.231, -1530.795, 6.398511, 213.778)
  forget_stored_cars_in_angled_cube(-1161.654, -1519.679, 2.121554, -1143.231, -1530.795, 6.398511, 213.778)
  @stored = false
  jump #MainCheck
end

/*
---- Airport Hangar for Trevor
*/
thread TrevorHangar
  name "TrevorHangar"
  var
    hangarMarker: Blip
  end
  @hangarMarker = add_blip_with_icon(1731.023, 3312.466, 39.43281, 359, 17)
  @hangarMarker.Selectable = true
  @hangarMarker.LongRange = true
  @hangarMarker.ShowOnMission = true

  var
    stored: bool
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
  end
  @stored = false

  :MainCheck
  wait 250
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, 1731.023, 3312.466, 39.43281, false)
  @intplayer = get_internal_player_index()
  if or
    @dist > 25
    @z > 45
    @z < 35
    $is_player_wasted != false
    $is_player_busted != false
    @intplayer != 2 // Automatically memorize cars, if a player switch occurs
  jump_if_false #RestoreVehicles

  if
    @stored == false
  jump_if_false #MainCheck

  store_cars_from_angled_cube(1749.443, 3299.457, 39.43281, 1712.507, 3325.671, 44.54997, 79.1128274, true)
  @stored = true
  jump #MainCheck

  :RestoreVehicles
  if
    @stored != false
  jump_if_false #MainCheck
  spawn_stored_cars_in_angled_cube(1749.443, 3299.457, 39.43281, 1712.507, 3325.671, 44.54997, 79.1128274)
  forget_stored_cars_in_angled_cube(1749.443, 3299.457, 39.43281, 1712.507, 3325.671, 44.54997, 79.1128274)
  @stored = false
  jump #MainCheck
end

/*
---- Car Respray 1 (Sandy Shores)
*/
thread CarSpray1
  name "CarSpray1"
  var
    marker: Blip
  end
  @marker = add_blip_with_icon(2349.535, 3134.186, 47.711, 402, 13)
  @marker.Selectable = true
  @marker.ShowOnMission = true

  var
    playerClose: bool
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerVehicle: GTA.Vehicle
    playerPos: Vector3
    vehicleStopped: bool
    x: float
    y: float
    z: float
    dist: float
    nofix: bool
    wantedlevel: int
  end
  @playerClose = false

  :CheckPlayerHasVehicle
  wait 0
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerVehicle = PED.GET_VEHICLE_PED_IS_USING(@playerPed)
  if
    @playerVehicle != 0
  jump_if_false #CheckPlayerHasVehicle

  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, 2349.535, 3134.186, 47.711, true)
  if
    @dist < 50
  jump_if_false #CheckPlayerHasVehicle

  GRAPHICS.DRAW_MARKER(1, 2349.535, 3134.186, 47.211, 0, 0, 0, 0, 0, 0, 1, 1, 1, 255, 173, 254, 192, false, false, 2, true, null_str, null_str, false)
  if and
    @dist < 5
    @playerClose == false
  jump_if_false #CheckPlayerHasVehicle

  @vehicleStopped = VEHICLE.IS_VEHICLE_STOPPED(@playerVehicle)
  if
    @vehicleStopped  != false
  jump_if_false #CheckPlayerHasVehicle
  @wantedlevel = PLAYER.GET_PLAYER_WANTED_LEVEL(@playerHandle)
  if
    @wantedLevel == 0
  jump_if_false #CheckVehicleCondition
  @wantedlevel = MISC.GET_FAKE_WANTED_LEVEL()

  :CheckVehicleCondition
  @nofix = VEHICLE.GET_DOES_VEHICLE_HAVE_DAMAGE_DECALS(@playerVehicle)
  if or
    @nofix != false
    @wantedlevel > 0
  jump_if_false #CheckPlayerHasVehicle

  gosub &GetCurrentPlayerMoney
  if
    $CurrentPlayerMoney >= 0 // For testing purposes, currently free
    // $CurrentPlayerMoney >= 1000
  jump_if_false #CheckPlayerHasVehicle

  $CurrentPlayerMoney -= 0 // For testing purposes, currently free
  // $CurrentPlayerMoney -= 1000
  gosub &SetCurrentPlayerMoney
  @playerClose = true
  $FixPlayerCar = @playerVehicle
  gosub &FixPlayerCarFunc

  :WaitPlayerLeave
  wait 0
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, 2349.535, 3134.186, 47.711, true)
  if
    @dist > 10
  jump_if_false #WaitPlayerLeave
  @playerClose = false
  jump #CheckPlayerHasVehicle
end

/*
---- Car Respray 2 (East Los Santos)
*/
thread CarSpray2
  name "CarSpray2"
  var
    marker: Blip
  end
  @marker = add_blip_with_icon(873.671, -2198.229, 30.021, 402, 13)
  @marker.Selectable = true
  @marker.ShowOnMission = true

  var
    playerClose: bool
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerVehicle: GTA.Vehicle
    playerPos: Vector3
    vehicleStopped: bool
    x: float
    y: float
    z: float
    dist: float
    nofix: bool
    wantedlevel: int
  end
  @playerClose = false

  :CheckPlayerHasVehicle
  wait 0
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerVehicle = PED.GET_VEHICLE_PED_IS_USING(@playerPed)
  if
    @playerVehicle != 0
  jump_if_false #CheckPlayerHasVehicle

  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, 873.671, -2198.229, 30.021, true)
  if
    @dist < 50
  jump_if_false #CheckPlayerHasVehicle

  GRAPHICS.DRAW_MARKER(1, 873.671, -2198.229, 29.521, 0, 0, 0, 0, 0, 0, 1, 1, 1, 255, 173, 254, 192, false, false, 2, true, null_str, null_str, false)
  if and
    @dist < 5
    @playerClose == false
  jump_if_false #CheckPlayerHasVehicle

  @vehicleStopped = VEHICLE.IS_VEHICLE_STOPPED(@playerVehicle)
  if
    @vehicleStopped  != false
  jump_if_false #CheckPlayerHasVehicle
  @wantedlevel = PLAYER.GET_PLAYER_WANTED_LEVEL(@playerHandle)
  if
    @wantedLevel == 0
  jump_if_false #CheckVehicleCondition
  @wantedlevel = MISC.GET_FAKE_WANTED_LEVEL()

  :CheckVehicleCondition
  @nofix = VEHICLE.GET_DOES_VEHICLE_HAVE_DAMAGE_DECALS(@playerVehicle)
  if or
    @nofix != false
    @wantedlevel > 0
  jump_if_false #CheckPlayerHasVehicle

  gosub &GetCurrentPlayerMoney
  if
    $CurrentPlayerMoney >= 0 // For testing purposes, currently free
    // $CurrentPlayerMoney >= 1000
  jump_if_false #CheckPlayerHasVehicle

  $CurrentPlayerMoney -= 0 // For testing purposes, currently free
  // $CurrentPlayerMoney -= 1000
  gosub &SetCurrentPlayerMoney
  @playerClose = true
  $FixPlayerCar = @playerVehicle
  gosub &FixPlayerCarFunc

  :WaitPlayerLeave
  wait 0
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, 873.671, -2198.229, 30.021, true)
  if
    @dist > 10
  jump_if_false #WaitPlayerLeave
  @playerClose = false
  jump #CheckPlayerHasVehicle
end

/*
---- Wasted-Busted Screen
*/
var
    is_player_wasted: bool
    is_player_busted: bool
end
thread WastedBusted
  name "WastedBusted"
  $is_player_wasted = false
  $is_player_busted = false

  var
    player: GTA.Player
    intplayer: int
    dead: bool
    effecttype: string
    scenetype: string
    scenesound: string
    respawntype: string
    sc: int
    loaded: bool
    ta: float
    soundplayed: bool
  end

  :wb_proc
  wait 0
  @player = PLAYER.GET_PLAYER_INDEX()

  // Is dead
  @dead = PLAYER.IS_PLAYER_DEAD(@player)
  if
    @dead == false
  jump_if_false #wb_death_scene

  // Is arrested
  @dead = PLAYER.IS_PLAYER_BEING_ARRESTED(@player, false)
  if
    @dead == false
  jump_if_false #wb_busted_scene
  jump #wb_proc

  // Death scene
  :wb_death_scene
  $is_player_wasted = true
  gosub #wb_start_scene_Default

  :wb_death_scene_wait
  wait 0
  gosub #wb_check_scene
  @dead = PLAYER.IS_PLAYER_DEAD(@player)
  if
    @dead == false
  jump_if_false #wb_death_scene_wait
  gosub #wb_end_scene
  $is_player_wasted = false

  // Money subtract
  gosub &GetCurrentPlayerMoney
  if
    $CurrentPlayerMoney >= 500
  jump_if_false #wb_proc
  $CurrentPlayerMoney -= 500
  gosub &SetCurrentPlayerMoney
  jump #wb_proc

  // Busted scene
  :wb_busted_scene
  $is_player_busted = true
  gosub #wb_start_scene_Default

  :wb_busted_scene_wait
  wait 0
  gosub #wb_check_scene
  @dead = PLAYER.IS_PLAYER_BEING_ARRESTED(@player, false)
  if
    @dead == false
  jump_if_false #wb_busted_scene_wait
  gosub #wb_end_scene
  $is_player_busted = false

  // Money subtract
  gosub &GetCurrentPlayerMoney
  if
    $CurrentPlayerMoney >= 500
  jump_if_false #wb_proc
  $CurrentPlayerMoney -= 500
  gosub &SetCurrentPlayerMoney
  jump #wb_proc

  // Sub: start scene
  :wb_start_scene_Default
  @intplayer = get_internal_player_index()
  if or
    @intplayer <= 0
    @intplayer > 2
  jump_if_false #wb_start_scene_Franklin
  @effecttype = "DeathFailMichaelIn"
  jump #wb_start_scene_Wasted

  :wb_start_scene_Franklin
  if
    @intplayer == 1
  jump_if_false #wb_start_scene_Trevor
  @effecttype = "DeathFailFranklinlIn"
  jump #wb_start_scene_Wasted

  :wb_start_scene_Trevor
  @effecttype = "DeathFailTrevorlIn"

  :wb_start_scene_Wasted
  if
    $is_player_wasted != false
  jump_if_false #wb_start_scene_Busted
  @scenetype = "DEATH_SCENE"
  @scenesound = "WastedSounds"
  @respawntype = "RESPAWN_W"
  jump #wb_start_scene_Start

  :wb_start_scene_Busted
  @scenetype = "BUSTED_SCENE"
  @scenesound = "BustedSounds"
  @respawntype = "RESPAWN_B"

  :wb_start_scene_Start
  @soundplayed = false
  reset_timer(0)
  MISC.SET_TIME_SCALE(0.2)
  CAM.SET_CAM_DEATH_FAIL_EFFECT_STATE(1)

  GRAPHICS.ANIMPOSTFX_PLAY(@effecttype, 0, true)
  AUDIO.START_AUDIO_SCENE(@scenetype)
  AUDIO.REQUEST_SCRIPT_AUDIO_BANK("OFFMISSION_WASTED", false, -1)
  AUDIO.PLAY_SOUND_FRONTEND(-1, "ScreenFlash", @scenesound, true)
  AUDIO.PLAY_SOUND_FRONTEND(-1, "Bed", @scenesound, true)
  @sc = GRAPHICS.REQUEST_SCALEFORM_MOVIE("MP_BIG_MESSAGE_FREEMODE")

  :wb_start_scene_load
  wait 0
  @loaded = GRAPHICS.HAS_SCALEFORM_MOVIE_LOADED(@sc)
  if
    @loaded != false
  jump_if_false #wb_start_scene_load
  GRAPHICS.BEGIN_SCALEFORM_MOVIE_METHOD(@sc, "RESET_MOVIE")
  GRAPHICS.END_SCALEFORM_MOVIE_METHOD()
  GRAPHICS.BEGIN_SCALEFORM_MOVIE_METHOD(@sc, "SHOW_SHARD_WASTED_MP_MESSAGE")
  GRAPHICS.BEGIN_TEXT_COMMAND_SCALEFORM_STRING("STRING")
  HUD.ADD_TEXT_COMPONENT_SUBSTRING_TEXT_LABEL(@respawntype)
  GRAPHICS.END_TEXT_COMMAND_SCALEFORM_STRING()
  GRAPHICS.END_SCALEFORM_MOVIE_METHOD()

  :wb_start_scene_ret
  return

  // Sub: check scene
  :wb_check_scene
  GRAPHICS.DRAW_SCALEFORM_MOVIE_FULLSCREEN(@sc, 0, 0, 0, 255, 0)
  @ta = get_timer(0)
  if and
    @ta > 0.3
    @soundplayed == false
  jump_if_false #wb_cs_nosound
  @soundplayed = true
  AUDIO.PLAY_SOUND_FRONTEND(-1, "Bed", @scenesound, true)

  :wb_cs_nosound
  return

  // Sub: end scene
  :wb_end_scene
  CAM.SET_CAM_DEATH_FAIL_EFFECT_STATE(0)
  GRAPHICS.ANIMPOSTFX_STOP(@effecttype)
  MISC.SET_TIME_SCALE(1)
  AUDIO.STOP_AUDIO_SCENE(@scenetype)
  GRAPHICS.SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(@sc)

  :wb_end_scene_ret
  return
end

/*
---- Dress Up Player
*/
/*
thread DressUp
  name "DressUp"
  var
    marker: Blip
  end
  @marker = add_blip_with_icon(-54.057, -1213.418, 28.676, 73, 13)

  // Player distance check
  var
    intplayer: int
    playerHandle: GTA.Player
    playerPed: GTA.Ped
    playerPos: Vector3
    x: float
    y: float
    z: float
    dist: float
    camera: GTA.Cam
  end

  :CheckConditions
  @intplayer = get_internal_player_index()
  wait 0
  if and
    $is_player_wasted == false
    $is_player_busted == false
    @intplayer != -1
  jump_if_false #CheckConditions

  // Query player's disatance to the save spot...
  @playerHandle = PLAYER.GET_PLAYER_INDEX()
  @playerPed = PLAYER.GET_PLAYER_PED(@playerHandle)
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -54.057, -1213.418, 28.676, true)

  // Draws a visible marker
  if
    @dist <= 50
  jump_if_false #CheckConditions
  GRAPHICS.DRAW_MARKER(1, -54.057, -1213.418, 27.676, 0, 0, 0, 0, 0, 0, 1, 1, 1, 255, 173, 254, 192, false, false, 2, true, null_str, null_str, false)

  // Activates wardrobe functionality
  if
    @dist <= 1
  jump_if_false #CheckConditions
  ENTITY.SET_ENTITY_HEADING(@playerPed, 132.771)
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  @camera = CAM.CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", true)
  CAM.SET_CAM_COORD(@camera, -56.801, -1215.375, 28.709)
  CAM.SET_CAM_ROT(@camera, 0.0, 0.0, 303.702, 2)
  CAM.RENDER_SCRIPT_CAMS(true, false, 0, false, false, 0)
  gosub_with_wb_check #ManageWardrobe
  if
    @camera != 0
  jump_if_false #Reenable
  CAM.RENDER_SCRIPT_CAMS(false, false, 0, false, false, 0)
  CAM.DESTROY_CAM(@camera, false)

  :Reenable
  PAD.ENABLE_ALL_CONTROL_ACTIONS(0)
  jump #CheckConditions

  :ManageWardrobe
  reset_timer(0)
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)

  :ManageWardrobe_DoMenu
  wait 2500


  // TODO here comes the dress-up code in loop!


  :ManageWardrobe_Return
  CAM.RENDER_SCRIPT_CAMS(false, false, 0, false, false, 0)
  CAM.DESTROY_CAM(@camera, false)

  :ManageWardrobe_ReturnWait
  wait 0
  @playerPos = ENTITY.GET_ENTITY_COORDS(@playerPed, false)
  @x = @playerPos.x
  @y = @playerPos.y
  @z = @playerPos.z
  @dist = MISC.GET_DISTANCE_BETWEEN_COORDS(@x, @y, @z, -54.057, -1213.418, 28.676, true)
  if
    @dist > 1.5
  jump_if_false #ManageWardrobe_ReturnWait
  return
end
*/
/*
---- Player Switch Functionality
*/
var
  PlayerSwitch_Enabled: bool
  PlayerSwitch_EnabledPlayers: bool[]
  PlayerSwitch_EnabledOnMission: bool
  PlayerSwitch_DisableFullPlayerRestore: bool
  PlayerSwitch_MichaelPed: GTA.Ped
  PlayerSwitch_FranklinPed: GTA.Ped
  PlayerSwitch_TrevorPed: GTA.Ped
end
thread PlayerSwitch
  name "PlayerSwitch"

  var
    playerUsed: bool[]
    txtMichael: string
    txtFranklin: string
    txtTrevor: string
  end

  // Initial setup
  $PlayerSwitch_Enabled = true
  $PlayerSwitch_EnabledPlayers = new bool[]
  $PlayerSwitch_EnabledPlayers.Length = 3
  $PlayerSwitch_EnabledPlayers[0] = true
  $PlayerSwitch_EnabledPlayers[1] = true
  $PlayerSwitch_EnabledPlayers[2] = true
  $PlayerSwitch_EnabledOnMission = false
  $PlayerSwitch_DisableFullPlayerRestore = false
  @playerUsed = new bool[]
  @playerUsed.Length = 3
  @playerUsed[0] = false
  @playerUsed[1] = false
  @playerUsed[2] = false
  reset_timer(0)
  reset_timer(1)
  reset_timer(2)

  // Graphics utils, that show text, require strings to be in variables!
  @txtMichael = "ACCNA_MIKE"
  @txtFranklin = "ACCNA_FRANKLIN"
  @txtTrevor = "ACCNA_TREVOR"

  var
    buttonpressed: bool
    playerindex: int
    wantedlevel: int
    playerid: GTA.Player
  end

  // Initial player is stored
  @playerindex = get_internal_player_index()
  if
    @playerindex != -1
  jump_if_false #CheckActivationConditions
  @playerUsed[@playerindex] = true
  store_player()

  // Activation
  :CheckActivationConditions
  wait 10
  @playerindex = get_internal_player_index()
  @buttonpressed = PAD.IS_CONTROL_PRESSED(0, 19) // INPUT_CHARACTER_WHEEL
  if and
    @buttonpressed != false
    $is_player_wasted == false
    $is_player_busted == false
    @playerindex != -1
  jump_if_false #CheckActivationConditions
  @playerid = PLAYER.GET_PLAYER_INDEX()
  @wantedlevel = PLAYER.GET_PLAYER_WANTED_LEVEL(@playerid)
  if
    @wantedLevel == 0
  jump_if_false #CheckActivationConditions_NoTrueWantedLevel
  @wantedlevel = MISC.GET_FAKE_WANTED_LEVEL()

  :CheckActivationConditions_NoTrueWantedLevel
  if and
    not is_on_mission()
    @wantedlevel == 0
  jump_if_false #CheckActivationConditions_OnMission
  jump #Activate

  :CheckActivationConditions_OnMission
  if
    $PlayerSwitch_EnabledOnMission != false
  jump_if_false #CheckActivationConditions

  :Activate
  MISC.SET_TIME_SCALE(0.125)
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  gosub_with_wb_check #HandlePlayerSwitch

  :Activate_End
  MISC.SET_TIME_SCALE(1.0)
  PAD.ENABLE_ALL_CONTROL_ACTIONS(0)
  jump #CheckActivationConditions

  // Player Switch Menu
  :HandlePlayerSwitch
  var
    selectedplayer: int
    lineindex: int
    timer: float
  end
  @selectedplayer = @playerindex
  reset_timer(4)

  :MenuControl
  wait 0
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  @buttonpressed = PAD.IS_DISABLED_CONTROL_PRESSED(0, 19) // INPUT_CHARACTER_WHEEL
  if
    @buttonpressed != false
  jump_if_false #HandlePlayerSwitch_Return
  @timer = get_timer(4)
  @buttonpressed = PAD.IS_DISABLED_CONTROL_PRESSED(0, 32) // INPUT_MOVE_UP_ONLY
  if and
    @buttonpressed != false
    @selectedplayer > 0
    @timer > 0.25
  jump_if_false #MenuControl_NextPlayer
  @selectedplayer -= 1
  reset_timer(4)
  jump #MenuControl_DrawMenu

  :MenuControl_NextPlayer
  @buttonpressed = PAD.IS_DISABLED_CONTROL_PRESSED(0, 33) // INPUT_MOVE_DOWN_ONLY
  if and
    @buttonpressed != false
    @selectedplayer < 2
    @timer > 0.25
  jump_if_false #MenuControl_DrawMenu
  @selectedplayer += 1
  reset_timer(4)

  :MenuControl_DrawMenu
  @lineindex = 0
  GRAPHICS.DRAW_RECT(0.5, 0.5, 1.0, 1.0, 255, 255, 255, 32, true)

  :MenuControl_DrawMenuLines
  gosub #DrawMenuLine
  if
    @lineindex < 2
  jump_if_false #MenuControl_DrawMenu_End
  @lineindex += 1
  jump #MenuControl_DrawMenuLines

  :MenuControl_DrawMenu_End
  jump #MenuControl

  :HandlePlayerSwitch_Return
  gosub #SwitchPlayers
  return

  // Draw menu line
  :DrawMenuLine
  var
    linetop: float
    line_textR: int
    line_textG: int
    line_textB: int
    col1: int
    col2: int
    col3: int
    col4: int
  end

  // Background rectangle
  if
    @selectedplayer == @lineindex
  jump_if_false #DrawMenuLine_Inactive
  @line_textR = 0
  @line_textG = 0
  @line_textB = 0
  @col1 = 255
  @col2 = 180
  @col3 = 0
  @col4 = 200
  jump #DrawMenuLine_Rect

  :DrawMenuLine_Inactive
  @line_textR = 128
  @line_textG = 128
  @line_textB = 128
  @col1 = 255
  @col2 = 255
  @col3 = 255
  @col4 = 128

  :DrawMenuLine_Rect
  @linetop = SYSTEM.TO_FLOAT(@lineindex)
  @linetop *= 0.1
  @linetop += 0.1
  GRAPHICS.DRAW_RECT(0.175, @linetop, 0.25, 0.05, @col1, @col2, @col3, @col4, true)
  @linetop -= 0.025
  HUD.SET_TEXT_FONT(0)
  HUD.SET_TEXT_SCALE(0.0, 0.5)
  HUD.SET_TEXT_CENTRE(false)
  HUD.SET_TEXT_COLOUR(@line_textR, @line_textG, @line_textB, 255)
  if
   @lineindex == 0
  jump_if_false #DrawMenuLine_Player1
  HUD.BEGIN_TEXT_COMMAND_DISPLAY_TEXT(@txtMichael)
  jump #DrawMenuLine_Text

  :DrawMenuLine_Player1
  if
    @lineindex == 1
  jump_if_false #DrawMenuLine_Player2
  HUD.BEGIN_TEXT_COMMAND_DISPLAY_TEXT(@txtFranklin)
  jump #DrawMenuLine_Text

  :DrawMenuLine_Player2
  HUD.BEGIN_TEXT_COMMAND_DISPLAY_TEXT(@txtTrevor)

  :DrawMenuLine_Text
  HUD.END_TEXT_COMMAND_DISPLAY_TEXT(0.05, @linetop, 0)
  return

  // Player switch implementation
  :SwitchPlayers
  var
    enabled: bool
  end

  @enabled = $PlayerSwitch_EnabledPlayers[@selectedplayer]
  if and
    @enabled != false
    @selectedplayer != @playerindex
  jump_if_false #SwitchPlayers_Return

  if
    $PlayerSwitch_DisableFullPlayerRestore == false
  jump_if_false #SwitchPlayers_NoRestore

  var
    modelhash: GTA.Hash
    carHash: GTA.Hash
    defOutFit: int[]
    defCarPriColor: int
    defCarSecColor: int
    hasModelLoaded: bool
    storedCar: bool
    storedOutfit: bool
    node: Vector3
    x: float
    y: float
    z: float
    oldPlayerPed: GTA.Ped
    newPlayerPed: GTA.Ped
    playerCarHandle: GTA.Vehicle
    i: int
    val: int
  end
  @defOutFit = new int[]
  @defOutFit.Length = 12

  if
    @selectedplayer == 0
  jump_if_false #SwitchPlayers_Model1
  @defCarPriColor = 64
  @defCarSecColor = 64
  @carHash = MISC.GET_HASH_KEY("stromberg")
  @modelhash = MISC.GET_HASH_KEY("player_zero")
  @defOutFit[0] = 0 // Head
  @defOutFit[1] = 0 // Beard
  @defOutFit[2] = 0 // Hair
  @defOutFit[3] = 22 // Torso
  @defOutFit[4] = 22 // Pants
  @defOutFit[5] = 0 // Hand
  @defOutFit[6] = 7 // Feet
  @defOutFit[7] = 0 // Invalid?
  @defOutFit[8] = 0 // Accessories
  @defOutFit[9] = 0 // Task?
  @defOutFit[10] = 0 // Decl?
  @defOutFit[11] = 0 // Jbib?
  jump #LoadPlayer

  :SwitchPlayers_Model1
  if
    @selectedplayer == 1
  jump_if_false #SwitchPlayers_Model2
  @defCarPriColor = 112
  @defCarSecColor = 112
  @carHash = MISC.GET_HASH_KEY("buffalo")
  @modelhash = MISC.GET_HASH_KEY("player_one")
  @defOutFit[0] = 0 // Head
  @defOutFit[1] = 0 // Beard
  @defOutFit[2] = 0 // Hair
  @defOutFit[3] = 13 // Torso
  @defOutFit[4] = 13 // Pants
  @defOutFit[5] = 0 // Hand
  @defOutFit[6] = 11 // Feet
  @defOutFit[7] = 0 // Invalid?
  @defOutFit[8] = 6 // Accessories
  @defOutFit[9] = 0 // Task?
  @defOutFit[10] = 0 // Decl?
  @defOutFit[11] = 0 // Jbib?
  jump #LoadPlayer

  :SwitchPlayers_Model2
  if
    @selectedplayer == 2
  jump_if_false #SwitchPlayers_Model2
  @defCarPriColor = 143
  @defCarSecColor = 35
  @carHash = MISC.GET_HASH_KEY("emperor2")
  @modelhash = MISC.GET_HASH_KEY("player_two")
  @defOutFit[0] = 0 // Head
  @defOutFit[1] = 0 // Beard
  @defOutFit[2] = 0 // Hair
  @defOutFit[3] = 5 // Torso
  @defOutFit[4] = 5 // Pants
  @defOutFit[5] = 2 // Hand
  @defOutFit[6] = 5 // Feet
  @defOutFit[7] = 0 // Invalid?
  @defOutFit[8] = 4 // Accessories
  @defOutFit[9] = 0 // Task?
  @defOutFit[10] = 0 // Decl?
  @defOutFit[11] = 0 // Jbib?

  :LoadPlayer
  STREAMING.REQUEST_MODEL(@modelhash)

  :LoadPlayer_Wait
  wait locked
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  @hasModelLoaded = STREAMING.HAS_MODEL_LOADED(@modelHash)
  if
    @hasModelLoaded != false
  jump_if_false #LoadPlayer_Wait

  :LoadCar_Check
  @storedCar = @playerUsed[@selectedplayer]
  @storedOutfit = @playerUsed[@selectedplayer]
  @timer = get_timer(@selectedplayer)
  if or
    @storedCar == false
    @timer > 240.0
  jump_if_false #SpawnPlayer_NoCar
  @storedCar = false
  STREAMING.REQUEST_MODEL(@carHash)

  :LoadCar_Wait
  wait locked
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  @hasModelLoaded = STREAMING.HAS_MODEL_LOADED(@carHash)
  if
    @hasModelLoaded != false
  jump_if_false #LoadCar_Wait
  jump #SpawnPlayer

  :SpawnPlayer_NoCar
  @carHash = 0

  :SpawnPlayer
  // Store current player
  reset_timer(@playerindex)
  @playerUsed[@playerindex] = true
  store_player()

  // Change protagonist
  @node = new Vector3
  PATHFIND.GET_CLOSEST_VEHICLE_NODE(-483.291, -308.783, 35.385, @node, 1, 3.0, 0.0)
  @x = @node.x
  @y = @node.y
  @z = @node.z
  MISC.CLEAR_AREA(@x, @y, @z, 25.0, true, false, true, false)
  @z += 1.0
  @oldPlayerPed = PLAYER.GET_PLAYER_PED(@playerid)
  ENTITY.SET_ENTITY_COORDS(@oldPlayerPed, @x, @y, @z, false, false, false, true)
  PLAYER.SET_PLAYER_MODEL(@playerid, @modelhash)
  cancel_auto_wasted_busted_return()
  @newPlayerPed = PLAYER.GET_PLAYER_PED(@playerid)
  PED.SET_PED_DEFAULT_COMPONENT_VARIATION(@newPlayerPed)
  if
    @storedOutfit == false
  jump_if_false #SpawnPlayer_IsStored

  // Player was not stored yet, we must setup an outfit!
  :SpawnPlayer_NotStored
  @i = 0

  :SpawnPlayer_NotStored_Loop
  @val = @defOutFit[@i]
  if or
    @val != 0
    @i != 7
  jump_if_false #SpawnPlayer_NotStored_Loop_Next
  PED.SET_PED_COMPONENT_VARIATION(@newPlayerPed, @i, @val, 0, 0)

  :SpawnPlayer_NotStored_Loop_Next
  @i += 1
  if
    @i > 11
  jump_if_false #SpawnPlayer_NotStored_Loop

  if
    @selectedplayer == 2
  jump_if_false #SpawnPlayer_IsStored
  PED.SET_PED_PROP_INDEX(@newPlayerPed, 0, 7, 0, true, 0) // Add a worker's hat for Trevor (dock worker outfit)

  // If player was stored, or the outfit was ready, we must check for stored car!
  :SpawnPlayer_IsStored
  if
    @storedCar == false
  jump_if_false #SpawnPlayer_Restore
  clear_stored_vehicle_for_player()
  reset_stored_location_for_player()

  :SpawnPlayer_Restore
  restore_player() // This is safe to call, even if the player was not stored earlier!
  if
    @storedCar == false
  jump_if_false #SpawnPlayer_Ready
  @z += 2.5
  @playerCarHandle = VEHICLE.CREATE_VEHICLE(@carHash, @x, @y, @z, 0.0, false, false, false)
  VEHICLE.SET_VEHICLE_COLOURS(@playerCarHandle, @defCarPriColor, @defCarSecColor)
  PED.SET_PED_INTO_VEHICLE(@newPlayerPed, @playerCarHandle, -1)
  ENTITY.SET_VEHICLE_AS_NO_LONGER_NEEDED(@playerCarHandle)

  :SpawnPlayer_Ready
  STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(@modelhash)
  if
    @carHash != 0
  jump_if_false #SpawnPlayer_Ready_Return
  STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(@carHash)

  :SpawnPlayer_Ready_Return
  return

  :SwitchPlayers_NoRestore
  var
    simplifiedped: GTA.Ped
  end

  if
    @selectedplayer == 0
  jump_if_false #SwitchPlayers_NoRestore_Franklin
  @simplifiedped = $PlayerSwitch_MichaelPed
  jump #SwitchPlayers_NoRestore_DoChange

  :SwitchPlayers_NoRestore_Franklin
  if
    @selectedplayer == 1
  jump_if_false #SwitchPlayers_NoRestore_Trevor
  @simplifiedped = $PlayerSwitch_FranklinPed
  jump #SwitchPlayers_NoRestore_DoChange

  :SwitchPlayers_NoRestore_Trevor
  @simplifiedped = $PlayerSwitch_TrevorPed

  :SwitchPlayers_NoRestore_DoChange
  store_player()
  PLAYER.CHANGE_PLAYER_PED(@playerid, @simplifiedped, false, false)
  cancel_auto_wasted_busted_return()
  reset_timer(@selectedplayer)
  @playerUsed[@selectedplayer] = true
  store_player() // Note: not 'restore'! We just store them...
  return

  :SwitchPlayers_Return
  return
end

/*
----
PLAYER MONEY GETTER FUNC
To query the current player's money, gosub into this thread
and retrieve the $CurrentPlayerMoney var
NOTE: This thread is being called from a gosub; we must not use local variables!
----
*/
var
  CurrentPlayerMoney: int
  _cpMoneyPlayerIndex_: int
  _cpMoneyStr_:  string
  _cpMoneyHash_: GTA.Hash
end
thread GetCurrentPlayerMoney
  $_cpMoneyPlayerIndex_ = get_internal_player_index()
  if
    $_cpMoneyPlayerIndex_ == -1
  jump_if_false #GetRealPlayerMoney_Michael
  $CurrentPlayerMoney = 999999999 // Net player can do anything!
  return

  :GetRealPlayerMoney_Michael
  if
    $_cpMoneyPlayerIndex_ == 0
  jump_if_false #GetRealPlayerMoney_Franklin
  $_cpMoneyStr_ = "SP0_TOTAL_CASH"
  jump #ReturnRealPlayerMoney

  :GetRealPlayerMoney_Franklin
  if
    $_cpMoneyPlayerIndex_ == 1
  jump_if_false #GetRealPlayerMoney_Trevor
  $_cpMoneyStr_ = "SP1_TOTAL_CASH"
  jump #ReturnRealPlayerMoney

  :GetRealPlayerMoney_Trevor
  $_cpMoneyStr_ = "SP2_TOTAL_CASH"

  :ReturnRealPlayerMoney
  $_cpMoneyHash_ = MISC.GET_HASH_KEY($_cpMoneyStr_)
  STATS.STAT_GET_INT($_cpMoneyHash_, $CurrentPlayerMoney, -1)
  return
end

/*
----
PLAYER MONEY SETTER FUNC
To set the current player's money, set the $CurrentPlayerMoney var,
and gosub into this thread
NOTE: This thread is being called from a gosub; we must not use local variables!
----
*/
thread SetCurrentPlayerMoney
  $_cpMoneyPlayerIndex_ = get_internal_player_index()
  if
    $_cpMoneyPlayerIndex_ == -1
  jump_if_false #SetRealPlayerMoney_Michael
  return

  :SetRealPlayerMoney_Michael
  if
    $_cpMoneyPlayerIndex_ == 0
  jump_if_false #SetRealPlayerMoney_Franklin
  $_cpMoneyStr_ = "SP0_TOTAL_CASH"
  jump #SetRealPlayerMoney

  :SetRealPlayerMoney_Franklin
  if
    $_cpMoneyPlayerIndex_ == 1
  jump_if_false #SetRealPlayerMoney_Trevor
  $_cpMoneyStr_ = "SP1_TOTAL_CASH"
  jump #SetRealPlayerMoney

  :SetRealPlayerMoney_Trevor
  $_cpMoneyStr_ = "SP2_TOTAL_CASH"

  :SetRealPlayerMoney
  $_cpMoneyHash_ = MISC.GET_HASH_KEY($_cpMoneyStr_)
  STATS.STAT_SET_INT($_cpMoneyHash_, $CurrentPlayerMoney, , true)
  return
end

/*
----
PLAYER CAR FIXER FUNC
To fix the player's car, se the $FixPlayerCar variable, and gosib into this thread
Wanted level will be cleared
NOTE: This thread is being called from a gosub; we must not use local variables!
----
*/
var
  FixPlayerCar: GTA.Vehicle
  _fixcarFade_: bool
  _fixcarWantedLevel_: int
  _fixcarNoFix_:  bool
  _fixcarRndColor1_: int
  _fixcarRndColor2_: int
  _fixcarPlayerHandle_: GTA.Player
end
thread FixPlayerCarFunc
  $_fixcarPlayerHandle_ = PLAYER.GET_PLAYER_INDEX()
  $_fixcarWantedLevel_ = PLAYER.GET_PLAYER_WANTED_LEVEL($_fixcarPlayerHandle_)
  if
    $_fixcarWantedLevel_ > 0
  jump_if_false #CheckFakeWantedLevel
  PLAYER.CLEAR_PLAYER_WANTED_LEVEL($_fixcarPlayerHandle_)
  jump #StartFadeOut

  :CheckFakeWantedLevel
  $_fixcarWantedLevel_ = MISC.GET_FAKE_WANTED_LEVEL()
  MISC.SET_FAKE_WANTED_LEVEL(0)

  :StartFadeOut
  CAM.DO_SCREEN_FADE_OUT(500)

  :WaitPlayerFadeOut
  wait 0
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  $_fixcarFade_ = CAM.IS_SCREEN_FADED_OUT()
  if
    $_fixcarFade_ != false
  jump_if_false #WaitPlayerFadeOut

  $_fixcarNoFix_ = FIRE.IS_ENTITY_ON_FIRE($FixPlayerCar)
  if
    $_fixcarNoFix_ != false
  jump_if_false #FixCar_2
  FIRE.STOP_ENTITY_FIRE($FixPlayerCar)

  :FixCar_2
  VEHICLE.SET_VEHICLE_FIXED($FixPlayerCar)
  VEHICLE.SET_VEHICLE_DEFORMATION_FIXED($FixPlayerCar)
  VEHICLE.SET_VEHICLE_NEEDS_TO_BE_HOTWIRED($FixPlayerCar, false)
  VEHICLE.SET_VEHICLE_ENGINE_HEALTH($FixPlayerCar, 1000.0)
  VEHICLE.SET_VEHICLE_PETROL_TANK_HEALTH($FixPlayerCar, 1000.0)
  VEHICLE.SET_VEHICLE_BODY_HEALTH($FixPlayerCar, 1000.0)
  VEHICLE.SET_VEHICLE_UNDRIVEABLE($FixPlayerCar, false)
  VEHICLE.SET_VEHICLE_ENGINE_CAN_DEGRADE($FixPlayerCar, false)
  VEHICLE.SET_VEHICLE_ENGINE_ON($FixPlayerCar, true, true, false)
  VEHICLE.SET_VEHICLE_DIRT_LEVEL($FixPlayerCar, 0)
  if
   $_fixcarWantedLevel_ > 0
  jump_if_false #StartFadeIn

  $_fixcarRndColor1_ = MISC.GET_RANDOM_INT_IN_RANGE(0, 100)
  $_fixcarRndColor2_ = MISC.GET_RANDOM_INT_IN_RANGE(0, 100)
  VEHICLE.CLEAR_VEHICLE_CUSTOM_PRIMARY_COLOUR($FixPlayerCar)
  VEHICLE.CLEAR_VEHICLE_CUSTOM_SECONDARY_COLOUR($FixPlayerCar)
  VEHICLE.SET_VEHICLE_COLOURS($FixPlayerCar, $_fixcarRndColor1_, $_fixcarRndColor2_)

  :StartFadeIn
  CAM.DO_SCREEN_FADE_IN(500)

  :WaitPlayerFadeIn
  wait 0
  PAD.DISABLE_ALL_CONTROL_ACTIONS(0)
  $_fixcarFade_ = CAM.IS_SCREEN_FADED_IN()
  if
    $_fixcarFade_ != false
  jump_if_false #WaitPlayerFadeIn
  PAD.ENABLE_ALL_CONTROL_ACTIONS(0)
  return
end

/*
---- SAVE GAME UTIL FUNC
NOTE: This thread is being called from a gosub; we must not use local variables!
*/
var
  SaveGameHours: int
  SaveGameMinutes: int
end
thread SaveGameFunc
  show_save_screen()
  CAM.DO_SCREEN_FADE_OUT(0)

  // Advance time 8 hours
  $SaveGameHours = CLOCK.GET_CLOCK_HOURS()
  $SaveGameMinutes = CLOCK.GET_CLOCK_MINUTES()
  $SaveGameHours += 8
  if
    $SaveGameHours > 23
  jump_if_false #AdvanceTime
  $SaveGameHours -= 24

  :AdvanceTime
  CLOCK.SET_CLOCK_TIME($SaveGameHours, $SaveGameMinutes, 0) // Seconds are meaningless in GTA V

  // In case we want to reinitialize world properties, that are not saved by YOS,
  // we must do them here!
  :DoWorldReinitActions
  if
    is_saved_game_loaded()
  jump_if_false #EndSub
  // Perform reinit actions here, if any

  jump #EndSub

  :EndSub
  wait 250
  CAM.DO_SCREEN_FADE_IN(1500)
  return
end





